-- Copyright (c) 2025 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at: http://license.coscl.org.cn/MulanPSL2
-- THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
-- EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
-- MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.

local lu = require 'luaunit'
local test_common = require 'test_common.utils'
local drive_collection = require 'drive.drive_collection'
local rpc_service_nvme_drive = require 'rpc_services.rpc_service_nvme_drive'
local task_mgmt = require 'mc.mdb.task_mgmt'
local NVME_MI_OPTIONS = require 'nvme.nvme_mi_protocol.nvme_mi_def'

TEST_nvme_method = {}

--[[测试用例描述:GetSmartInfo方法调用测试
    预制条件:支持mctp的nvme mi硬盘对象加载
    操作步骤：
    调用获取SmartLog的rpc方法
    预期结果：
    1.返回成功
    2.报文解析符合预期]]
function TEST_nvme_method:test_get_smart_info_success()
    local rsp = '1236198646'
    drive_collection.get_instance().nvme_list[1] = {
        nvme_mi_mctp_obj = {
            queue = function (func)
                func()
            end,
            nvme_mi_obj = {
                SmartLog = function()
                    return {value = function ()
                        return rsp
                    end}
                end
            }
        },
        Slot = 8
    }
    local ok, ret = pcall(function ()
        return rpc_service_nvme_drive:get_smart_info('Drive_9_010102', 0)
    end)
    lu.assertIsTrue(ok)
    for i = #rsp, 1, -1 do
        lu.assertEquals(rsp:byte(i), ret[#rsp - i + 1])
    end
    drive_collection.get_instance().nvme_list[1] = nil
end

--[[测试用例描述:GetSmartInfo方法调用测试
    预制条件:支持mctp的nvme mi硬盘对象加载
    操作步骤：
    调用获取非标准SmartLog的rpc方法
    预期结果：
    1.返回成功
    2.报文解析符合预期]]
function TEST_nvme_method:test_get_vendor_smart_info_success()
    local rsp = '1236198646'
    drive_collection.get_instance().nvme_list[1] = {
        nvme_mi_mctp_obj = {
            queue = function (func)
                func()
            end,
            nvme_mi_obj = {
                RawRequest = function()
                    return {value = function ()
                        return rsp
                    end}
                end
            }
        },
        Slot = 8
    }
    local ok, ret = pcall(function ()
        return rpc_service_nvme_drive:get_smart_info('Drive_9_010102', 1)
    end)
    lu.assertIsTrue(ok)
    for i = #rsp, 1, -1 do
        lu.assertEquals(rsp:byte(i), ret[#rsp - i + 1])
    end
    drive_collection.get_instance().nvme_list[1] = nil
end

--[[测试用例描述:GetSmartInfo方法调用测试
    预制条件:支持mctp的nvme mi硬盘对象不支持mctp
    操作步骤：
    调用获取SmartLog的rpc方法
    预期结果：
    1.返回失败
    2.错误码符合预期]]
function TEST_nvme_method:test_get_smart_info_fail()
    drive_collection.get_instance().nvme_list[1] = {
        nvme_mi_mctp_obj = false,
        Slot = 66
    }
    local ok, err = pcall(function ()
        rpc_service_nvme_drive:get_smart_info('Drive_67_010102', 0)
    end)
    lu.assertIsFalse(ok)
    lu.assertEquals(err.name, 'ActionNotSupported')
    drive_collection.get_instance().nvme_list[1] = nil
end

--[[测试用例描述:GetSmartInfo方法调用测试
    预制条件:支持mctp的nvme mi硬盘对象加载但SmartLog返回nil
    操作步骤：
    调用获取SmartLog的rpc方法
    预期结果：
    1.返回失败
    2.错误码符合预期]]
function TEST_nvme_method:test_get_smart_info_nil_response()
    drive_collection.get_instance().nvme_list[1] = {
        nvme_mi_mctp_obj = {
            queue = function (func)
                func()
            end,
            nvme_mi_obj = {
                SmartLog = function()
                    return {value = function ()
                        return nil
                    end}
                end
            }
        },
        Slot = 8
    }
    local ok, err = pcall(function ()
        return rpc_service_nvme_drive:get_smart_info('Drive_9_010102', 0)
    end)
    lu.assertIsFalse(ok)
    lu.assertEquals(err.name, 'ActionNotSupported')
    drive_collection.get_instance().nvme_list[1] = nil
end

--[[测试用例描述:SendNvmeMICommand方法调用测试
    预制条件:支持mctp的nvme mi硬盘对象加载
    操作步骤：
    调用获取SendNvmeMICommand的rpc方法
    预期结果：
    1.返回成功
    2.报文解析符合预期]]
function TEST_nvme_method:test_send_nvmemi_command_success()
    local rsp = '\x00\x40\x00\x00'
    drive_collection.get_instance().nvme_list[1] = {
        nvme_mi_mctp_obj = {
            queue = function (func)
                func()
            end,
            nvme_mi_obj = {
                RawRequest = function()
                    return {value = function ()
                        return rsp
                    end}
                end
            }
        },
        Slot = 54
    }
    local ok, status, nvmersq, rsp_data = pcall(function ()
        return rpc_service_nvme_drive:send_nvmemi_command('Drive_55_010102', 4, 3, 0, {})
    end)
    lu.assertIsTrue(ok)
    lu.assertEquals(status, 0)
    lu.assertEquals(nvmersq, 64)
    lu.assertEquals(#rsp_data, 0)
    drive_collection.get_instance().nvme_list[1] = nil
end

--[[测试用例描述:SendNvmeMICommand方法调用测试
    预制条件:支持mctp的nvme mi硬盘对象不支持mctp
    操作步骤：
    调用获取SendNvmeMICommand的rpc方法
    预期结果：
    1.返回失败
    2.错误码符合预期]]
function TEST_nvme_method:test_send_nvmemi_command_fail()
    drive_collection.get_instance().nvme_list[1] = {
        nvme_mi_mctp_obj = false,
        Slot = 24
    }
    local ok, err = pcall(function ()
        rpc_service_nvme_drive:send_nvmemi_command('Drive_25_010102', 0)
    end)
    lu.assertIsFalse(ok)
    lu.assertEquals(err.name, 'ActionNotSupported')
    drive_collection.get_instance().nvme_list[1] = nil
end

--[[测试用例描述:SendNvmeMICommand方法调用测试
    预制条件:支持mctp的nvme mi硬盘对象加载但RawRequest返回nil
    操作步骤：
    调用获取SendNvmeMICommand的rpc方法
    预期结果：
    1.返回失败
    2.错误码符合预期]]
function TEST_nvme_method:test_send_nvmemi_command_nil_response()
    drive_collection.get_instance().nvme_list[1] = {
        nvme_mi_mctp_obj = {
            queue = function (func)
                func()
            end,
            nvme_mi_obj = {
                RawRequest = function()
                    return {value = function ()
                        return nil
                    end}
                end
            }
        },
        Slot = 54
    }
    local ok, err = pcall(function ()
        return rpc_service_nvme_drive:send_nvmemi_command('Drive_55_010102', 4, 3, 0, {})
    end)
    lu.assertIsFalse(ok)
    lu.assertEquals(err.name, 'ActionNotSupported')
    drive_collection.get_instance().nvme_list[1] = nil
end

--[[测试用例描述:GetIdentifyData方法调用测试
    预制条件:支持mctp的nvme mi硬盘对象加载
    操作步骤：
    调用获取GetIdentifyData的rpc方法
    预期结果：
    1.返回成功
    2.报文解析符合预期]]
function TEST_nvme_method:test_get_identify_data_success()
    local rsp = '49816898446'
    drive_collection.get_instance().nvme_list[1] = {
        nvme_mi_mctp_obj = {
            queue = function (func)
                func()
            end,
            nvme_mi_obj = {
                IdentifyNS = function()
                    return {value = function ()
                        return rsp
                    end}
                end
            }
        },
        Slot = 13
    }
    local ok, ret = pcall(function ()
        return rpc_service_nvme_drive:get_identify_data('Drive_14_010102', 0)
    end)
    print(ret)
    lu.assertIsTrue(ok)
    for i = #rsp, 1, -1 do
        lu.assertEquals(rsp:byte(i), ret[#rsp - i + 1])
    end
    drive_collection.get_instance().nvme_list[1] = nil
end

--[[测试用例描述:GetIdentifyData方法调用测试
    预制条件:支持mctp的nvme mi硬盘对象不支持mctp
    操作步骤：
    调用获取GetIdentifyData的rpc方法
    预期结果：
    1.返回失败
    2.错误码符合预期]]
function TEST_nvme_method:test_get_identify_data_fail()
    drive_collection.get_instance().nvme_list[1] = {
        nvme_mi_mctp_obj = false,
        Slot = 13
    }
    local ok, err = pcall(function ()
        rpc_service_nvme_drive:get_identify_data('Drive_14_010102', 0)
    end)
    lu.assertIsFalse(ok)
    lu.assertEquals(err.name, 'ActionNotSupported')
    drive_collection.get_instance().nvme_list[1] = nil
end

--[[测试用例描述:GetIdentifyData方法调用测试
    预制条件:支持mctp的nvme mi硬盘对象加载但IdentifyNS返回nil
    操作步骤：
    调用获取GetIdentifyData的rpc方法
    预期结果：
    1.返回失败
    2.错误码符合预期]]
function TEST_nvme_method:test_get_identify_data_nil_response()
    drive_collection.get_instance().nvme_list[1] = {
        nvme_mi_mctp_obj = {
            nvme_mi_obj = {
                IdentifyNS = function()
                    return {value = function ()
                        return nil
                    end}
                end
            }
        },
        Slot = 13
    }
    local ok = pcall(function ()
        return rpc_service_nvme_drive:get_identify_data('Drive_14_010102', 0)
    end)
    lu.assertIsFalse(ok)
    drive_collection.get_instance().nvme_list[1] = nil
end

--[[测试用例描述:GetTelemetryData方法调用测试
    预制条件:支持mctp的nvme mi硬盘对象加载
    操作步骤：
    调用获取GetTelemetryData的rpc方法
    预期结果：
    1.返回成功
    2.taskid符合预期]]
function TEST_nvme_method:test_get_telemetry_data_success()
    local rsp = '8541446'
    drive_collection.get_instance().nvme_list[1] = {
        nvme_mi_mctp_obj = {
            queue = function (func)
                func()
            end,
            nvme_mi_obj = {
                RawRequest = function()
                    return {value = function ()
                        return rsp
                    end}
                end
            }
        },
        Slot = 13
    }
    local create_code = task_mgmt.create_code
    task_mgmt.create_task = function()
        return create_code.TASK_CREATE_SUCCESSFUL, 123, 4566
    end
    local ok, ret = pcall(function()
        return rpc_service_nvme_drive:get_telemetry_data('Drive_14_010102', _, 'Host')
    end)
    lu.assertIsTrue(ok)
    lu.assertEquals(ret, 4566)
    drive_collection.get_instance().nvme_list[1] = nil
end

--[[测试用例描述:GetTelemetryData方法调用测试
    预制条件:支持mctp的nvme mi硬盘对象不支持mctp
    操作步骤：
    调用获取GetTelemetryData的rpc方法
    预期结果：
    1.返回失败
    2.错误码符合预期]]
function TEST_nvme_method:test_get_telemetry_data_fail()
    drive_collection.get_instance().nvme_list[1] = {
        nvme_mi_mctp_obj = false,
        Slot = 13
    }
    local ok, err = pcall(function()
        return rpc_service_nvme_drive:get_telemetry_data('Drive_14_010102', _, 'Host')
    end)
    lu.assertIsFalse(ok)
    lu.assertEquals(err.name, 'ActionNotSupported')
    drive_collection.get_instance().nvme_list[1] = nil
end

--[[测试用例描述:GetTelemetryData方法调用测试
    预制条件:支持mctp的nvme mi硬盘对象加载但task创建失败
    操作步骤：
    调用获取GetTelemetryData的rpc方法
    预期结果：
    1.返回失败
    2.错误码符合预期]]
function TEST_nvme_method:test_get_telemetry_data_task_create_fail()
    drive_collection.get_instance().nvme_list[1] = {
        nvme_mi_mctp_obj = {
            nvme_mi_obj = {
                RawRequest = function()
                    return {value = function ()
                    end}
                end
            }
        },
        Slot = 13
    }
    local create_code = task_mgmt.create_code
    task_mgmt.create_task = function()
        return create_code.TASK_CREATE_FAILED, nil, nil
    end
    local ok, err = pcall(function()
        return rpc_service_nvme_drive:get_telemetry_data('Drive_14_010102', _, 'Host')
    end)
    lu.assertIsFalse(ok)
    lu.assertEquals(err.name, 'DuplicateExportingErr')
    drive_collection.get_instance().nvme_list[1] = nil
end

return TEST_nvme_method